package com.young.rabbitmq.dlx;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.young.rabbitmq.util.ConnectionUtil;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * 限长队列，在配置了死信队列的前提下，在达到最大队列长度后如果还有消息进来，那么之前的没有被消费的消息将会被转发到消息队列中
 */
public class LimitLengthQueueToDLX {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtil.buildConnection();
        Channel channel = connection.createChannel();

        // 声明允许发送到死信队列的交换机以及队列
        // 声明DIRECT 类型的交换机
        channel.exchangeDeclare("allow_dlx_max_length_change",BuiltinExchangeType.DIRECT,true);

        // 创建map对象，里面存放一些用于创建队列的一些属性
        Map<String,Object> map = new HashMap<>();
        // 通过该属性定义，在一定条件下通过my_dlx_exchange将消息转投到死信交换机
        map.put("x-dead-letter-exchange","my_dlx_exchange");
        // 通过该属性可以将队列声明为一个带有过期时间的队列
        map.put("x-max-length",2);
        // 声明队列并指定创建队列的一些属性
        channel.queueDeclare("allow_dlx_max_length_queue", true, false, false, map);
        // 绑定队列和交换机
        channel.queueBind("allow_dlx_max_length_queue","allow_dlx_max_length_change","dlx_max_length_key");


        // 声明死信交换机以及死信队列
        channel.exchangeDeclare("my_dlx_exchange",BuiltinExchangeType.DIRECT);
        // 声明死信队列
        channel.queueDeclare("my_dlx_queue",true,false,false,null);
        // 注意：在绑定死信队列和死交换机的时候必须保证 路由键和要转发到死信队列的队列的路由键保持一致，否则会无法转发到死信队列
        // 如这里的路由键，和上方绑定的路由键就是相同的
        channel.queueBind("my_dlx_queue","my_dlx_exchange","dlx_max_length_key");


        for (int i = 0; i < 3; i++) {
            // 发送消息
            channel.basicPublish("allow_dlx_change","dlx_routingkey",null,("第 "+i+" 条发往过期队列的消息").getBytes(StandardCharsets.UTF_8));
        }


        // 9、关闭资源
        channel.close();
        connection.close();
    }
}
